package com.jxd.project.travel.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jxd.project.travel.dao.IEmpDao;
import com.jxd.project.travel.dao.ITicketDao;
import com.jxd.project.travel.dao.ITravelDao;
import com.jxd.project.travel.model.Ticket;
import com.jxd.project.travel.model.Travel;
import com.jxd.project.travel.service.ITravelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @ClassName TravelServiceImpl
 * @Description TODO
 * @Author 邢子剑
 * @Date 2025/9/24 上午8:59
 * @Version 1.0
 */
@Service
public class TravelServiceImpl extends ServiceImpl<ITravelDao, Travel> implements ITravelService {
    // 数字大写映射
    private static final String[] DIGITS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
    // 整数部分单位（索引对应位数：0-个位，1-十位，2-百位...）
    private static final String[] UNITS = {"", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "兆"};

    @Autowired
    private ITravelDao travelDao;

    @Autowired
    private ITicketDao ticketDao;

    @Autowired
    private IEmpDao empDao;

    @Override
    public IPage<Travel> getTravelList(int pageNum, int pageSize, String travelId, String startTime, String endTime, int empno) {
        IPage<Travel> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Travel> queryWrapper = new QueryWrapper<>();
        if (travelId != null) {
            queryWrapper.like("travelId", travelId);
        }
        if (startTime != null && !startTime.isEmpty()) {
            queryWrapper.ge("reimbursedTime", startTime);
        }
        if (endTime != null && !endTime.isEmpty()) {
            queryWrapper.le("reimbursedTime", endTime);
        }
        if (empno != 0) {
            queryWrapper.eq("empno", empno);
        }
        return travelDao.selectPage(page, queryWrapper);
    }

    @Override
    public int insertTravel(Travel travel) {
        // 生成travelId：empno + 年月日时分秒（格式如100120251010163045）
        Integer empno = travel.getEmpno();
        if (empno == null) {
            throw new RuntimeException("员工工号不能为空");
        }
        // 格式化当前时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String timeStr = sdf.format(new Date());
        String travelIdStr = empno.toString() + timeStr;
        // 拼接生成travelId
        String travelId;
        try {
            travelId = travelIdStr;
        } catch (NumberFormatException e) {
            throw new RuntimeException("生成travelId失败：" + travelIdStr, e);
        }
        // 设置到实体中
        travel.setTravelId(travelId);

        // 执行插入操作
        return travelDao.insert(travel);
    }

    @Override
    public boolean updateTravel(Travel travel) {
        LambdaUpdateWrapper<Travel> queryWrapper = new LambdaUpdateWrapper<>();
        queryWrapper.eq(Travel::getTravelId, travel.getTravelId());
        return travelDao.update(travel, queryWrapper) > 0;
    }

    @Override
    public boolean deleteTravel(List<String> travelIds) {
        int affectedRows = travelDao.deleteByTravelId(travelIds);
        return affectedRows > 0;
    }



    @Override
    public Travel getOne(String travelId) {
        LambdaQueryWrapper<Travel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Travel::getTravelId, travelId);
        return travelDao.selectOne(queryWrapper);
    }

    @Override
    public String moneyToChinese(double money) {
        if (money < 0) {
            throw new IllegalArgumentException("金额不能为负数");
        }

        // 转换为分（四舍五入），避免浮点数精度问题
        long totalCent = Math.round(money * 100);
        long integerPart = totalCent / 100; // 整数部分（元）
        int decimalPart = (int) (totalCent % 100); // 小数部分（角分）

        String integerStr = convertInteger(integerPart);
        String decimalStr = convertDecimal(decimalPart);

        // 处理特殊情况
        if (integerPart == 0 && decimalPart == 0) {
            return "零元整";
        }
        if (integerPart == 0) {
            return "零元" + decimalStr;
        }
        if (decimalPart == 0) {
            return integerStr + "元整";
        }
        return integerStr + "元" + decimalStr;
    }

    /**
     * 部门经理看到本部门的待审核差旅信息，总经理看到所有部门的待审核差旅信息
     * @param pageNum
     * @param pageSize
     * @param empno
     * @return
     */
    @Override
    public IPage<Travel> getTravelListByEmpno(int pageNum, int pageSize, int empno ,int[] roleids, boolean isAll) {
        IPage<Travel> page = new Page<>(pageNum, pageSize);
        if (roleids != null && Arrays.stream(roleids).anyMatch(role -> role == 3)) {
            // 部门经理：获取本部门
            int deptno = empDao.selectById(empno).getDeptno();
            if (isAll) {
                // 全部信息：本部门所有状态（忽略approval条件）
                return travelDao.getTravelListByDeptAndApproval(page, deptno, -1);
            } else {
                // 待审核：本部门 approval=1
                return travelDao.getTravelListByDeptAndApproval(page, deptno, 1);
            }

        } else if (roleids != null && Arrays.stream(roleids).anyMatch(role -> role == 2)) {
            // 总经理：不分部门，直接取 approval=2
            if (isAll) {
                // 全部信息：所有部门所有状态（忽略approval条件）
                return travelDao.getTravelListByApproval(page, -1);
            } else {
                // 待审核：所有部门 approval=2
                return travelDao.getTravelListByApproval(page, 2);
            }

        } else {
            return new Page<>(pageNum, pageSize);
        }
    }

    /**
     * 根据差旅id获取票据信息
     * @param travelId
     * @return
     */
    @Override
    public List<Ticket> getTicketByTravelId(String travelId) {
        LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Ticket::getTravelId, travelId)
                .orderByAsc(Ticket::getStartTime);
        return ticketDao.selectList(queryWrapper);
    }

    /**
     * 更新差旅审批状态（通过）
     * @param travelId
     * @return
     */
    @Override
    public boolean updateApprovalStatus1(String travelId, String managerOpinion, String directorOpinion) {
        LambdaUpdateWrapper<Travel> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Travel::getTravelId, travelId)
                // 更新审批状态（原逻辑：审批级别+1）
                .setSql("approval = approval + 1")
                // 保存部门经理意见（如果有值）
                .set(StringUtils.hasText(managerOpinion), Travel::getManagerOpinion, managerOpinion)
                // 保存总经理意见（如果有值）
                .set(StringUtils.hasText(directorOpinion), Travel::getDirectorOpinion, directorOpinion);

        return travelDao.update(null, updateWrapper) > 0;
    }

    /**
     * 更新差旅审批状态（驳回）
     *
     * @param travelId
     * @param managerOpinion
     * @param directorOpinion
     * @return
     */
    @Override
    public boolean updateApprovalStatus2(String travelId, String managerOpinion, String directorOpinion) {
        LambdaUpdateWrapper<Travel> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Travel::getTravelId, travelId)
                // 更新审批状态为驳回（原逻辑：重置为0）
                .setSql("approval = 0")
                // 保存部门经理意见（如果有值）
                .set(StringUtils.hasText(managerOpinion), Travel::getManagerOpinion, managerOpinion)
                // 保存总经理意见（如果有值）
                .set(StringUtils.hasText(directorOpinion), Travel::getDirectorOpinion, directorOpinion);

        return travelDao.update(null, updateWrapper) > 0;
    }

    @Override
    public int getApprovalByTravelId(String travelId) {
        LambdaQueryWrapper<Travel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Travel::getTravelId, travelId);
        Travel travel = travelDao.selectOne(queryWrapper);
        return travel.getApproval();
    }

    @Override
    public int getRejectCount(int empno) {
        LambdaQueryWrapper<Travel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Travel::getEmpno, empno)
                .eq(Travel::getApproval, 0)
                .nested(q -> q
                        // 部门经理意见：非null且非空字符串
                        .isNotNull(Travel::getManagerOpinion)
                        .ne(Travel::getManagerOpinion, "")
                        // 或者
                        .or()
                        // 总经理意见：非null且非空字符串
                        .isNotNull(Travel::getDirectorOpinion)
                        .ne(Travel::getDirectorOpinion, "")
                );

        return Math.toIntExact(travelDao.selectCount(queryWrapper));
    }

    /**
     * 转换整数部分为中文大写
     */
    private static String convertInteger(long integerPart) {
        if (integerPart == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        String numStr = Long.toString(integerPart);
        int len = numStr.length();
        boolean hasZero = false; // 标记是否有未处理的零

        for (int i = 0; i < len; i++) {
            int digit = numStr.charAt(i) - '0';
            int unitIndex = len - 1 - i; // 计算当前位对应的单位索引

            if (digit == 0) {
                hasZero = true;
                // 处理万、亿等級位（即使当前位为0，若前面有数字需保留级位）
                if (unitIndex % 4 == 0 && unitIndex != 0) { // 级位索引：4(万)、8(亿)、12(兆)...
                    if (sb.length() > 0) {
                        sb.append(UNITS[unitIndex]);
                        hasZero = false;
                    }
                }
            } else {
                if (hasZero) {
                    sb.append(DIGITS[0]); // 补零
                    hasZero = false;
                }
                sb.append(DIGITS[digit]).append(UNITS[unitIndex]);
            }
        }
        return sb.toString();
    }

    /**
     * 转换小数部分（角分）为中文大写
     */
    private static String convertDecimal(int decimalPart) {
        if (decimalPart == 0) {
            return "";
        }

        int jiao = decimalPart / 10; // 角
        int fen = decimalPart % 10;  // 分
        StringBuilder sb = new StringBuilder();

        if (jiao != 0) {
            sb.append(DIGITS[jiao]).append("角");
        } else if (fen != 0) {
            // 角为0但分不为0时，补零
            sb.append(DIGITS[0]);
        }

        if (fen != 0) {
            sb.append(DIGITS[fen]).append("分");
        } else if (jiao != 0) {
            // 分为0但角不为0时，加"整"
            sb.append("整");
        }

        return sb.toString();
    }


}
